﻿using DataProcess.Core;
using DataProcess.Core.Tools;
using DataProcess.Interface;
using DevExpress.XtraDataLayout;
using DevExpress.XtraEditors;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq.Expressions;
using System.Text;
using System.Windows.Forms;

namespace DataProcess4Net48.Extensions
{

    public static class XtraFormExtension
    {
        /// <summary>
        /// 为XtraTabControl添加一个页面
        /// </summary>
        /// <param name="tabControl">页面要添加到的XtraTabControl</param>
        /// <param name="frm">页面窗体</param>
        /// <param name="pageName">页面Name</param>
        /// <param name="pageText">页面Text</param>
        /// <returns></returns>
        public static OperateResult AddXtraForm<T>(this DevExpress.XtraTab.XtraTabControl tabControl, T frm, string pageName, string pageText = "") where T : DevExpress.XtraEditors.XtraForm
        {
            if (frm == null) return OperateResultConstructor.Error(false, "传入的XtraForm不能为null");
            if (string.IsNullOrEmpty(pageName)) return OperateResultConstructor.Error(false, "传入的pageName不能为空");
            DevExpress.XtraTab.XtraTabPage tabpage = null;
            //判断是否已经有了修改的tabpage
            foreach (DevExpress.XtraTab.XtraTabPage page in tabControl.TabPages)
            {
                if (page.Name == pageName)
                {
                    tabpage = page;
                }
            }

            if (tabpage != null)
            {
                tabControl.SelectedTabPage = tabpage;
                return OperateResultConstructor.Error(false, $"【{tabpage.Text}】的页面已经存在,请先完成之前操作");
            }
            else
            {
                frm.TopLevel = false;
                frm.Dock = System.Windows.Forms.DockStyle.Fill;
                frm.Visible = true;
                DevExpress.XtraTab.XtraTabPage page = new DevExpress.XtraTab.XtraTabPage
                {
                    Name = pageName,
                    Text = string.IsNullOrEmpty(pageText) ? frm.Text : pageText
                };
                page.Controls.Add(frm);
                tabControl.TabPages.Add(page);
                tabControl.SelectedTabPage = page;
            }
            return OperateResultConstructor.Sucess();
        }

        public static void RemovePage(this DevExpress.XtraTab.XtraTabControl tabControl, DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs e)
        {
            if (e.Page is DevExpress.XtraTab.XtraTabPage page)
            {
                tabControl.RemovePage(page);
            }
        }


        /// <summary>
        /// 为XtraTabControl添加一个页面
        /// </summary>
        /// <param name="tabControl">页面要添加到的XtraTabControl</param>
        /// <param name="control">页面窗体</param>
        /// <param name="pageName">页面Name</param>
        /// <param name="pageText">页面Text</param>
        /// <returns></returns>
        public static OperateResult AddUserControlASPage<T>(this DevExpress.XtraTab.XtraTabControl tabControl, T control, string pageName, string pageText) where T : XtraUserControl
        {
            if (control == null) return OperateResultConstructor.Error(false, "传入的UserControl不能为null");
            if (string.IsNullOrEmpty(pageName)) return OperateResultConstructor.Error(false, "传入的pageName不能为空");
            DevExpress.XtraTab.XtraTabPage tabpage = null;
            //判断是否已经有了修改的tabpage
            foreach (DevExpress.XtraTab.XtraTabPage page in tabControl.TabPages)
            {
                if (page.Name == pageName)
                {
                    tabpage = page;
                }
            }

            if (tabpage != null)
            {
                tabControl.SelectedTabPage = tabpage;
                return OperateResultConstructor.Error(false, $"【{tabpage.Text}】的页面已经存在,请先完成之前操作");
            }
            else
            {
                control.Dock = DockStyle.Fill;
                control.Visible = true;
                DevExpress.XtraTab.XtraTabPage page = new DevExpress.XtraTab.XtraTabPage
                {
                    Name = pageName,
                    Text = string.IsNullOrEmpty(pageText) ? control.Text : pageText
                };
                page.Controls.Add(control);
                tabControl.TabPages.Add(page);
                tabControl.SelectedTabPage = page;
            }
            return OperateResultConstructor.Sucess();
        }



        /// <summary>
        /// 为XtraTabControl添加一个页面
        /// </summary>
        /// <param name="tabControl">页面要添加到的XtraTabControl</param>
        /// <param name="frm">页面窗体</param>
        /// <param name="pageName">页面Name</param>
        /// <param name="pageText">页面Text</param>
        /// <returns></returns>
        //public static FuncResult<bool> AddDetailsForm<T>(this XtraTabControl tabControl, T frm, string pageName, string pageText = "") where T : Form, IDetailsForm
        //{
        //    if (frm == null) return FuncHelper.Error(false, "传入的XtraForm不能为null");
        //    XtraTabPage tabpage = null;
        //    //判断是否已经有了修改的tabpage
        //    foreach (XtraTabPage page in tabControl.TabPages)
        //    {
        //        if (page.Name == pageName)
        //        {
        //            tabpage = page;
        //        }
        //    }

        //    if (tabpage != null)
        //    {
        //        tabControl.SelectedTabPage = tabpage;
        //        return FuncHelper.Error(false, $"【{tabpage.Text}】的页面已经存在,请先完成之前操作");
        //    }
        //    else
        //    {
        //        frm.TopLevel = false;
        //        frm.Dock = DockStyle.Fill;
        //        frm.FormBorderStyle = FormBorderStyle.None;
        //        frm.Visible = true;
        //        XtraTabPage page = new XtraTabPage();
        //        page.Name = pageName;
        //        page.Controls.Add(frm);
        //        page.Text = string.IsNullOrEmpty(pageText) ? frm.Text : pageText;
        //        tabControl.TabPages.Add(page);
        //        tabControl.SelectedTabPage = page;
        //    }
        //    return FuncHelper.Sucess();
        //}

        public static void RemovePage(this DevExpress.XtraTab.XtraTabControl tabControl, DevExpress.XtraTab.XtraTabPage tabPage)
        {
            foreach (var ctrl in tabPage.Controls)
            {
                if (ctrl is IDisposable _d)
                {
                    _d.Dispose();
                    _d = null;
                }
            }
            tabControl.TabPages.Remove(tabPage);
            tabPage.Dispose();
        }

        /// <summary>
        /// 为控件绑定数据源
        /// </summary>
        /// <typeparam name="T">绑定对象的类型</typeparam>
        /// <param name="lookUpEdit"></param>
        /// <param name="dataSource">要绑定的数据源</param>
        /// <param name="displayExpression">选择后显示以及编辑可器模糊查询的属性表达式</param>
        /// <param name="keyvalueExpression">选择项取值的属性表达式</param>
        /// <param name="columnsExpression">下拉列表要显示的列的表达式</param>
        public static void BindingDataSource<T>(this DevExpress.XtraEditors.LookUpEdit lookUpEdit, List<T> dataSource, Expression<Func<T, object>> displayExpression, Expression<Func<T, object>> keyvalueExpression, Expression<Func<T, object[]>> columnsExpression)
        {
            //绑定数据源
            if (dataSource == null)
            {
                lookUpEdit.Properties.DataSource = new List<T>();
            }
            else
            {
                lookUpEdit.Properties.DataSource = new BindingList<T>(dataSource);
            }

            //获取display表达式中属性的名称
            string displayName = PropertyHelper.GetMemberName(displayExpression);
            if (!string.IsNullOrEmpty(displayName))
            {
                lookUpEdit.Properties.DisplayMember = displayName;
            }

            //获取value表达式中属性的名称
            string valueName = PropertyHelper.GetMemberName(keyvalueExpression);
            if (!string.IsNullOrEmpty(valueName))
            {
                lookUpEdit.Properties.ValueMember = valueName;
                lookUpEdit.Properties.KeyMember = valueName;
            }

            List<string> columns = PropertyHelper.GetPropertyNames(columnsExpression);
            if (columns.Count > 0)
            {
                lookUpEdit.Properties.Columns.Clear();
                foreach (string col in columns)
                {
                    lookUpEdit.Properties.Columns.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo(col));
                }
            }
        }

        /// <summary>
        /// 为控件绑定数据源
        /// </summary>
        /// <typeparam name="T">绑定对象的类型</typeparam>
        /// <param name="lookUpEdit"></param>
        /// <param name="dataSource">要绑定的数据源</param>
        /// <param name="displayExpression">选择后显示以及编辑可器模糊查询的属性表达式</param>
        /// <param name="valueExpression">选择后保存字段的属性表达式</param>
        /// <param name="keyvalueExpression">选择项取值的属性表达式</param>
        /// <param name="columnsExpression">下拉列表要显示的列的表达式</param>
        public static void BindingDataSource<T>(this DevExpress.XtraEditors.LookUpEdit lookUpEdit, List<T> dataSource, Expression<Func<T, object>> displayExpression, Expression<Func<T, object>> valueExpression, Expression<Func<T, object>> keyvalueExpression, Expression<Func<T, object[]>> columnsExpression)
        {
            //绑定数据源
            if (dataSource == null)
            {
                lookUpEdit.Properties.DataSource = new List<T>();
            }
            else
            {
                lookUpEdit.Properties.DataSource = new BindingList<T>(dataSource);
            }

            //获取display表达式中属性的名称
            string displayName = PropertyHelper.GetMemberName(displayExpression);
            if (!string.IsNullOrEmpty(displayName))
            {
                lookUpEdit.Properties.DisplayMember = displayName;
            }

            //获取value表达式中属性的名称
            string valueName = PropertyHelper.GetMemberName(valueExpression);
            if (!string.IsNullOrEmpty(valueName))
            {
                lookUpEdit.Properties.ValueMember = valueName;
            }
            string keyName = PropertyHelper.GetMemberName(keyvalueExpression);
            if (!string.IsNullOrEmpty(keyName))
            {
                lookUpEdit.Properties.KeyMember = keyName;
            }


            List<string> columns = PropertyHelper.GetPropertyNames(columnsExpression);
            if (columns.Count > 0)
            {
                lookUpEdit.Properties.Columns.Clear();
                foreach (string col in columns)
                {
                    lookUpEdit.Properties.Columns.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo(col));
                }
            }
        }

        /// <summary>
        /// 为LookUpEdit绑定数据源
        /// </summary>
        /// <typeparam name="T">绑定对象的类型</typeparam>
        /// <param name="lookUpEdit"></param>
        /// <param name="dataSource">要绑定的数据源</param>
        /// <param name="displayName">选择后显示以及编辑可器模糊查询的属性名</param>
        /// <param name="valueName">选择项取值的属性名</param>
        /// <param name="keyName">key</param>
        /// <param name="columns">下拉列表要显示的列的表达式</param>
        public static void BindingDataSource<T>(this DevExpress.XtraEditors.LookUpEdit lookUpEdit, List<T> dataSource, string displayName, string keyvalueName, List<string> columns)
        {
            //绑定数据源
            if (dataSource == null)
            {
                lookUpEdit.Properties.DataSource = new List<T>();
            }
            else
            {
                lookUpEdit.Properties.DataSource = new BindingList<T>(dataSource);
            }
            //绑定数据源
            lookUpEdit.Properties.DataSource = new BindingList<T>(dataSource);
            if (!string.IsNullOrEmpty(displayName)) lookUpEdit.Properties.DisplayMember = displayName;
            if (!string.IsNullOrEmpty(keyvalueName))
            {
                lookUpEdit.Properties.ValueMember = keyvalueName;
                lookUpEdit.Properties.KeyMember = keyvalueName;
            }

            if (columns != null && columns.Count > 0)
            {
                lookUpEdit.Properties.Columns.Clear();
                foreach (string col in columns)
                {
                    lookUpEdit.Properties.Columns.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo(col));
                }
            }
        }

        /// <summary>
        /// 保存布局文件到指定的文件夹下
        /// </summary>
        /// <param name="layoutControl">布局控件</param>
        /// <param name="type">实体类型</param>
        /// <param name="FormSize">布局控件所属的窗体大小</param>
        /// <param name="folderPath">要保存文件到的文件夹路径</param>
        public static void SaveLayoutAndSizeToXml(this DataLayoutControl layoutControl, Type type, Size FormSize, string folderPath = "")
        {
            string fileName = string.Empty;
            string sizeName = string.Empty;
            if (string.IsNullOrEmpty(folderPath))
            {
                fileName = $@"{AppDomain.CurrentDomain.BaseDirectory}\{type.Name}.layout";
                sizeName = $@"{AppDomain.CurrentDomain.BaseDirectory}\{type.Name}.size";
            }
            else
            {
                fileName = $@"{folderPath}\{fileName}";
                sizeName = $@"{folderPath}\{sizeName}";
            }
            try
            {
                if (!File.Exists(fileName))
                {
                    using (File.Create(fileName)) { }
                }

                if (!File.Exists(sizeName))
                {
                    using (File.Create(sizeName)) { }
                }

                layoutControl.SaveLayoutToXml(fileName);
                File.WriteAllText(sizeName, FormSize.FromStruct(), Encoding.UTF8);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static Size RestoreLayoutAndSizeFromXml(this DataLayoutControl layoutControl, Type type, string folderPath = "")
        {
            string fileName = string.Empty;
            string sizeName = string.Empty;
            if (string.IsNullOrEmpty(folderPath))
            {
                fileName = $@"{AppDomain.CurrentDomain.BaseDirectory}\{type.Name}.layout";
                sizeName = $@"{AppDomain.CurrentDomain.BaseDirectory}\{type.Name}.size";
            }
            else
            {
                fileName = $@"{folderPath}\{fileName}";
                sizeName = $@"{folderPath}\{sizeName}";
            }

            if (File.Exists(fileName))
            {
                layoutControl.RestoreLayoutFromXml(fileName);
            }


            if (!File.Exists(sizeName)) return default;
            {
                try
                {
                    return File.ReadAllText(sizeName).ToStruct<Size>();
                }
                catch
                {
                    return default;
                }
            }
        }


    }
}
